//HLSL shaders

//--------------------------------------------------------------------------------------
// Defines
//--------------------------------------------------------------------------------------

#define TONEMAPPING_MODE_0
//#define AA_MODE_0
//#define AA_MODE_1
#define AA_MODE_2
#define DoF
#define LensFlares
#define FakeGodRays //need to ajust, can not working
//#define DoF_Vignetting
#define DoF_Manual
//#define DoF_Auto
//#define DoF_PentagonShape



//--------------------------------------------------------------------------------------
// Vectors, floats and etc.
//--------------------------------------------------------------------------------------
static float2 screenRes = {1920,1080};//Screen Resolution, for example 3840x2160


//Dof params
float PI = 3.14159265;

float focalDepth = 90.5;
float focalLength = 80.5;
float fstop = 90.5;

float vignint = 4; //vignetting intensity

float ndofstart = 80.002; //near dof blur start
float ndofdist = 4.50; //near dof blur falloff distance
float fdofstart = 80.001; //far dof blur start
float fdofdist = 4.50; //far dof blur falloff distance

float2 focus = float2(0.5,0.5);//autofocus position

float CoC = 0.030;// table is here http://en.wikipedia.org/wiki/Circle_of_confusion
float namount = 0.00010;//feel the power of noise))
float DOFdownsample = 4.0;
float maxblur = 2.1;//maximum bluring

static const int samples = 12; //samples on the first ring 
static const int rings = 2; //ring count, can't be more than 2

float threshold = 0.7;//dof brightness treshold
float gain = 27.0;

float bias = 0.01;//bokeh bias
float fringe = 0.2;

float znear = 161.0; //camera clipping start
float zfar = 6550.0; //camera clipping end

float feather = 1.1; //pentagon shape feather

//Bloom
static const float thresh = 0.10;
float4 threshhold = {thresh, 0/(0-thresh), 0.0, 0.0};
float BloomIntensity = 0.1;

//SSAA,NFAA,FXAA
float _OffsetScale = 9.0;
float _BlurRadius = 9.0;

float2 texel = {0.0009765625,0.00130208333333333333333333333333};

//Tonemapping
float _ExposureAdjustment = 7.10;//Adjust Exposure; Настройка Экспозиции
static const float gray = 0.0;
static const float white = 0.0;
float4 _HdrParams = {gray,gray,gray,white*white};

float4 paramsS = {1.0,1.0,1.0,1.0};//Цветокорекция тени
float4 paramsM = {1.0,1.0,1.0,1.0};//Цветокорекция полутени(среднего значения)
float4 paramsH = {1.0,1.0,1.0,1.0};//Цветокорекция ярких областей
float _Saturation = 1.20;//Насыщенность

//Bloom 2
static const float thresh2 = 0.92;// Treshold - работает юзай его от него зависит и блум(который не активен по некоторым причинам) и эффект линз
float4 threshhold2 = {thresh2, 0/(0-thresh2), 0.0, 0.0};
float BloomIntensity2 = 18.5;

//+++++++++++++++++++++++++++++
//external parameters, do not modify
//+++++++++++++++++++++++++++++
//keyboard controlled temporary variables (in some versions exists in the config file). Press and hold key 1,2,3...8 together with PageUp or PageDown to modify. By default all set to 1.0
float4 tempF1; //0,1,2,3
float4 tempF2; //5,6,7,8
float4 tempF3; //9,0
//x=Width, y=1/Width, z=ScreenScaleY, w=1/ScreenScaleY
float4 ScreenSize;
//x=generic timer in range 0..1, period of 16777216 ms (4.6 hours), w=frame time elapsed (in seconds)
float4 Timer;
//adaptation delta time for focusing
float FadeFactor;

//--------------------------------------------------------------------------------------
// Textures
//--------------------------------------------------------------------------------------

texture2D texColor;
texture2D texDepth;
texture2D texNoise;
texture2D texPalette;
texture2D texFocus; //computed focusing depth
texture2D texCurr; //4*4 texture for focusing
texture2D texPrev; //4*4 texture for focusing

//--------------------------------------------------------------------------------------
// Functions
//--------------------------------------------------------------------------------------

float Luminance( float3 c )
{
	return dot( c, float3(0.22, 0.707, 0.071) );
}

float vignette(float2 coord, float _int)
{
	float2 coords = coord;
	coords = (coords - 0.5) * 2.0;		
	float coordDot = dot (coords,coords);	
	return 1.0 - coordDot * _int * 0.1;
}

//--------------------------------------------------------------------------------------
// Sampler Inputs
//--------------------------------------------------------------------------------------

sampler2D SamplerColor = sampler_state
{
	Texture   = <texColor>;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = NONE;//NONE;
	AddressU  = Clamp;
	AddressV  = Clamp;
	SRGBTexture=FALSE;
	MaxMipLevel=0;
	MipMapLodBias=0;
};

sampler2D InputSampler = sampler_state
{
    Texture = (texColor);
    MinFilter = Linear;
    MagFilter = Linear;
    MipFilter = Linear;
    AddressU   = Clamp;
	AddressV   = Clamp;
	SRGBTexture=FALSE;
	MaxMipLevel=0;
	MipMapLodBias=0;
};

sampler2D SamplerDepth = sampler_state
{
	Texture   = <texDepth>;
	MinFilter = POINT;
	MagFilter = POINT;
	MipFilter = NONE;
	AddressU  = Clamp;
	AddressV  = Clamp;
	SRGBTexture=FALSE;
	MaxMipLevel=0;
	MipMapLodBias=0;
};

sampler2D SamplerNoise = sampler_state
{
	Texture   = <texNoise>;
	MinFilter = POINT;
	MagFilter = POINT;
	MipFilter = NONE;//NONE;
	AddressU  = Wrap;
	AddressV  = Wrap;
	SRGBTexture=FALSE;
	MaxMipLevel=0;
	MipMapLodBias=0;
};

sampler2D SamplerPalette = sampler_state
{
	Texture   = <texPalette>;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = NONE;//NONE;
	AddressU  = Clamp;
	AddressV  = Clamp;
	SRGBTexture=FALSE;
	MaxMipLevel=0;
	MipMapLodBias=0;
};

//for focus computation
sampler2D SamplerCurr = sampler_state
{
	Texture   = <texCurr>;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = LINEAR;//NONE;
	AddressU  = Clamp;
	AddressV  = Clamp;
	SRGBTexture=FALSE;
	MaxMipLevel=0;
	MipMapLodBias=0;
};

//for focus computation
sampler2D SamplerPrev = sampler_state
{
	Texture   = <texPrev>;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = NONE;
	AddressU  = Clamp;
	AddressV  = Clamp;
	SRGBTexture=FALSE;
	MaxMipLevel=0;
	MipMapLodBias=0;
};
//for dof only in PostProcess techniques
sampler2D SamplerFocus = sampler_state
{
	Texture   = <texFocus>;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = NONE;
	AddressU  = Clamp;
	AddressV  = Clamp;
	SRGBTexture=FALSE;
	MaxMipLevel=0;
	MipMapLodBias=0;
};

struct VS_OUTPUT_POST
{
	float4 vpos  : POSITION;
	float2 txcoord : TEXCOORD0;
};

struct VS_INPUT_POST
{
	float3 pos  : POSITION;
	float2 txcoord : TEXCOORD0;
};

struct VS_OUTPUT_POST_SSAA
{
	float4 vpos : POSITION;
	float2 uv[5] : TEXCOORD0;
};

struct VS_OUTPUT_POST_NFAA
{
	float4 vpos : POSITION;
	float2 uv[8] : TEXCOORD0;
};

//--------------------------------------------------------------------------------------
// Functions
//--------------------------------------------------------------------------------------

//--------------------------------------------------------------------------------------
// Vertex Shader Input
//--------------------------------------------------------------------------------------

VS_OUTPUT_POST VS_PostProcess(VS_INPUT_POST IN)
{
	VS_OUTPUT_POST OUT;

	float4 pos=float4(IN.pos.x,IN.pos.y,IN.pos.z,1.0);

	OUT.vpos=pos;
	OUT.txcoord.xy=IN.txcoord.xy;

	return OUT;
}



//--------------------------------------------------------------------------------------
// Pixel Shader Effects
//--------------------------------------------------------------------------------------

//--------------------------------------------------------------------------------------
//AntiAliasing
//--------------------------------------------------------------------------------------

float4 SSAA(VS_OUTPUT_POST_SSAA i, float2 vPos : VPOS) : COLOR 
{
		float4 outColor;
		
	    float t = Luminance( tex2D( InputSampler, i.uv[0] ).xyz );
		float l = Luminance( tex2D( InputSampler, i.uv[1] ).xyz);
		float r = Luminance( tex2D( InputSampler, i.uv[2] ).xyz);
		float b = Luminance( tex2D( InputSampler, i.uv[3] ).xyz);
	 
	    float2 n = float2( -( t - b ), r - l );
	    float nl = length( n );
	 
	    if ( nl < (1.0 / 16.0) )
			outColor = tex2D( InputSampler, i.uv[4] );
	    else {
			n *= texel.xy / nl;
	 
			float4 o = tex2D( InputSampler, i.uv[4]);
			float4 t0 = tex2D( InputSampler, i.uv[4] + n * 0.5) * 0.9;
			float4 t1 = tex2D( InputSampler, i.uv[4] - n * 0.5) * 0.9;
			float4 t2 = tex2D( InputSampler, i.uv[4] + n) * 0.75;
			float4 t3 = tex2D( InputSampler, i.uv[4] - n) * 0.75;
	 
			outColor = (o + t0 + t1 + t2 + t3) / 4.3;
	    }
	    
	    return outColor;
}

float4 NFAA (VS_OUTPUT_POST_NFAA i, float2 vPos : VPOS) : COLOR 
{	
	// get luminance values
	//  maybe: experiment with different luminance calculations
	float topL = Luminance( tex2D(InputSampler, i.uv[0]).rgb );
	float bottomL = Luminance( tex2D(InputSampler, i.uv[1]).rgb );
	float rightL = Luminance( tex2D(InputSampler, i.uv[2]).rgb );
	float leftL = Luminance( tex2D(InputSampler, i.uv[3]).rgb );
	float leftTopL = Luminance( tex2D(InputSampler, i.uv[4]).rgb );
	float leftBottomL = Luminance( tex2D(InputSampler, i.uv[5]).rgb );
	float rightBottomL = Luminance( tex2D(InputSampler, i.uv[6]).rgb );
	float rightTopL = Luminance( tex2D(InputSampler, i.uv[7]).rgb );
	
	// 2 triangle subtractions
	float sum0 = dot(float3(1,1,1), float3(rightTopL,bottomL,leftTopL));
	float sum1 = dot(float3(1,1,1), float3(leftBottomL,topL,rightBottomL));
	float sum2 = dot(float3(1,1,1), float3(leftTopL,rightL,leftBottomL));
	float sum3 = dot(float3(1,1,1), float3(rightBottomL,leftL,rightTopL));

	// figure out "normal"
	float2 blurDir = float2((sum0-sum1), (sum3-sum2));
	blurDir *= texel.xy * _BlurRadius;

	// reconstruct normal uv
	float2 uv_ = (i.uv[0] + i.uv[1]) * 0.5;
	 
	float4 returnColor = tex2D(InputSampler, uv_);
	returnColor += tex2D(InputSampler, uv_+ blurDir.xy);
	returnColor += tex2D(InputSampler, uv_ - blurDir.xy);
	returnColor += tex2D(InputSampler, uv_ + float2(blurDir.x, -blurDir.y));
	returnColor += tex2D(InputSampler, uv_ - float2(blurDir.x, -blurDir.y));

	return returnColor * 0.2;
}

float _EdgeThresholdMin = 0.125;
float _EdgeThreshold = 0.25;
float _EdgeSharpness = 4.0;

struct VS_OUTPUT_POST_FXAA {
	float4 vpos : SV_POSITION;
	float2 uv : TEXCOORD0;
	float4 interpolatorA : TEXCOORD1;
	float4 interpolatorB : TEXCOORD2;
	float4 interpolatorC : TEXCOORD3;
};

VS_OUTPUT_POST_FXAA VS_PostProcessFXAA (VS_INPUT_POST v)
{
	VS_OUTPUT_POST_FXAA o;
	float4 pos=float4(v.pos.x,v.pos.y,v.pos.z,1.0);
	o.vpos=pos;
	
	o.uv = v.txcoord.xy;
	
	float4 extents;
	float2 offset = ( texel.xy ) * 0.5f;
	extents.xy = v.txcoord.xy - offset;
	extents.zw = v.txcoord.xy + offset;

	float4 rcpSize;
	rcpSize.xy = -texel.xy * 0.5f;
	rcpSize.zw = texel.xy * 0.5f;			
	
	o.interpolatorA = extents;
	o.interpolatorB = rcpSize;
	o.interpolatorC = rcpSize;
	
	o.interpolatorC.xy *= 4.0;
	o.interpolatorC.zw *= 4.0;
	
	return o;
}

#define FxaaTexTop(t, p) tex2Dlod(t, float4(p, 0.0, 0.0))

inline float TexLuminance( float2 uv )
{
	return Luminance(FxaaTexTop(InputSampler, uv).rgb);
}

float3 FxaaPixelShader(float2 pos, float4 extents, float4 rcpSize, float4 rcpSize2)
{
	float lumaNw = TexLuminance(extents.xy);
	float lumaSw = TexLuminance(extents.xw);
	float lumaNe = TexLuminance(extents.zy);
	float lumaSe = TexLuminance(extents.zw);
	
	float3 centre = FxaaTexTop(InputSampler, pos).rgb;
	float lumaCentre = Luminance(centre);
	
	float lumaMaxNwSw = max( lumaNw , lumaSw );
	lumaNe += 1.0/384.0;
	float lumaMinNwSw = min( lumaNw , lumaSw );
	
	float lumaMaxNeSe = max( lumaNe , lumaSe );
	float lumaMinNeSe = min( lumaNe , lumaSe );
	
	float lumaMax = max( lumaMaxNeSe, lumaMaxNwSw );
	float lumaMin = min( lumaMinNeSe, lumaMinNwSw );
	
	float lumaMaxScaled = lumaMax * _EdgeThreshold;
	
	float lumaMinCentre = min( lumaMin , lumaCentre );
	float lumaMaxScaledClamped = max( _EdgeThresholdMin , lumaMaxScaled );
	float lumaMaxCentre = max( lumaMax , lumaCentre );
	float dirSWMinusNE = lumaSw - lumaNe;
	float lumaMaxCMinusMinC = lumaMaxCentre - lumaMinCentre;
	float dirSEMinusNW = lumaSe - lumaNw;
	
	if(lumaMaxCMinusMinC < lumaMaxScaledClamped)
		return centre;
	
	float2 dir;
	dir.x = dirSWMinusNE + dirSEMinusNW;
	dir.y = dirSWMinusNE - dirSEMinusNW;
	
	dir = normalize(dir);			
	float3 col1 = FxaaTexTop(InputSampler, pos.xy - dir * rcpSize.zw).rgb;
	float3 col2 = FxaaTexTop(InputSampler, pos.xy + dir * rcpSize.zw).rgb;
	
	float dirAbsMinTimesC = min( abs( dir.x ) , abs( dir.y ) ) * _EdgeSharpness;
	dir = clamp(dir.xy/dirAbsMinTimesC, -2.0, 2.0);
	
	float3 col3 = FxaaTexTop(InputSampler, pos.xy - dir * rcpSize2.zw).rgb;
	float3 col4 = FxaaTexTop(InputSampler, pos.xy + dir * rcpSize2.zw).rgb;
	
	float3 rgbyA = col1 + col2;
	float3 rgbyB = ((col3 + col4) * 0.25) + (rgbyA * 0.25);
	
	if((Luminance(rgbyA) < lumaMin) || (Luminance(rgbyB) > lumaMax))
		return rgbyA * 0.5;
	else
		return rgbyB;
}

float4 FXAA (VS_OUTPUT_POST_FXAA i, float2 vPos : VPOS) : COLOR
{
	float3 color = FxaaPixelShader(i.uv, i.interpolatorA, i.interpolatorB, i.interpolatorC);
	return float4(color, 1.0);
}


//--------------------------------------------------------------------------------------
// Bloom
//--------------------------------------------------------------------------------------

float4 PS_ProcessBloom (VS_OUTPUT_POST IN, float2 vPos : VPOS) : COLOR 
{
	float4 col = tex2D(InputSampler, IN.txcoord);
	float4 color = tex2Dlod(InputSampler, float4(IN.txcoord,0,9));
	color = max(float4(0.0,0.0,0.0,0.0), color-threshhold.x);
	float4 toBlend = saturate (color * BloomIntensity);
	
	return 1-(1.00-col)*(1.17-toBlend);
}


//--------------------------------------------------------------------------------------
//DoF (READY TO USE)
//--------------------------------------------------------------------------------------

//Bokeh

float penta(float2 coords) //pentagonal shape
{
	float scale = float(rings) - 1.5;
	float4  HS0 = float4( -20.0, -15.0, -15.0, -20.0);
	float4  HS1 = float4( -20.0, -15.0, -15.0, -20.0);
	float4  HS2 = float4( -20.0, -15.0, -15.0, -20.0);
	float4  HS3 = float4( -20.0, -15.0, -15.0, -20.0);
	float4  HS4 = float4( -20.0, -15.0, -15.0, -20.0);
	float4  HS5 = float4( -20.0, -15.0, -15.0, -20.0);
	
	float4  one = float4(8.0, 8.0, 8.0, 8.0);
	
	float4 P = float4(coords,float2(scale, scale)); 
	
	float4 dist = float4(4.0, 4.0, 4.0, 4.0);
	float inorout = 0.0;
	
	dist.x = dot( P, HS0 );
	dist.y = dot( P, HS1 );
	dist.z = dot( P, HS2 );
	dist.w = dot( P, HS3 );
	
	dist = smoothstep( -feather, feather, dist );
	
	inorout += dot( dist, one );
	
	dist.x = dot( P, HS4 );
	dist.y = HS5.w - abs( P.z );
	
	dist = smoothstep( -feather, feather, dist );
	inorout += dist.x;
	
	return saturate( inorout );
}

float linearize(float depth)
{
	return -zfar * znear / (depth * (zfar - znear) - zfar);
}

float2 rand(float2 coord) //generating noise/pattern texture for dithering
{
	float noiseX = ((frac(3.0-coord.x*(screenRes.x/0.2))*3.25)+(frac(coord.y*(screenRes.y/0.2))*3.75))*0.1-0.2;
	float noiseY = ((frac(3.0-coord.x*(screenRes.x/0.2))*3.75)+(frac(coord.y*(screenRes.y/0.2))*3.25))*0.1-0.2;
	
	return float2(noiseX,noiseY);
}

float4 colorDof(float2 coords,float blur) //processing the sample
{
	float4 colDF = float4(1,1,1,1);
	
	colDF.x = tex2D(InputSampler,coords + float2(0.0,1.0)*texel*fringe*blur).x;
	colDF.y = tex2D(InputSampler,coords + float2(-0.866,-0.5)*texel*fringe*blur).y;
	colDF.z = tex2D(InputSampler,coords + float2(0.866,-0.5)*texel*fringe*blur).z;
	
	float3 lumcoeff = float3(0.299,0.587,0.114);
	float lum = dot(colDF.xyz,lumcoeff);
	float thresh = max((lum-threshold)*gain, 0.0);
	float3 nullcol = float3(0,0,0);
	colDF.xyz +=lerp(nullcol,colDF.xyz,thresh*blur);
	return colDF;
}

float4 PS_ProcessDoFBokeh(VS_OUTPUT_POST IN, float2 vPos : VPOS) : COLOR 
{
	float depth = linearize(tex2D(SamplerDepth,IN.txcoord.xy).x);
	
	float fDepth = focalDepth;
	
	#ifdef DoF_Auto
		fDepth = linearize(tex2D(SamplerDepth,focus).x);
	#endif
	
	float blur = 2.0;
	#ifdef DoF_Manual
		float a = depth-fDepth; //focal plane
		float b = (a-fdofstart)/fdofdist; //far DoF
		float c = (-a-ndofstart)/ndofdist; //near Dof
		blur = (a>0.0)?b:c;
	#else
		float f = focalLength; //focal length in mm
		float d = fDepth*1000.0; //focal plane in mm
		float o = depth*1000.0; //depth in mm
		
		float a = (o*f)/(o-f); 
		float b = (d*f)/(d-f); 
		float c = (d-f)/(d*fstop*CoC); 
		
		blur = abs(a-b)*c;
	#endif
	blur = saturate(blur);
	float2 noise = rand(IN.txcoord.xy)*namount*blur;
	
	float w = (1.0/screenRes.x)*blur*maxblur+noise.x;
	float h = (1.0/screenRes.y)*blur*maxblur+noise.y;
	
	float4 col = float4(0,0,0,1);
	
	if(blur < 0.05) //some optimization thingy
	{
		col = tex2D(InputSampler, IN.txcoord.xy);
	}
	else
	{
	col = tex2D(InputSampler, IN.txcoord.xy);
	float s = 1.0;
	int ringsamples;
	for (int i = 1; i <= rings; i += 1)
	{
		ringsamples = i * samples;
		for (int j = 0 ; j < ringsamples ; j += 1)
		{
			float step = PI*2.0 / ringsamples;
			float pw = cos(j*step)*i;
			float ph = sin(j*step)*i;
			float p = 1.0;
			#ifdef DoF_PentagonShape 
				p = penta(float2(pw,ph));
			#endif
			col.xyz += colorDof(IN.txcoord.xy + float2(pw*w,ph*h),blur).xyz;  
			s += 1.0*lerp(1.0,i/rings,bias)*p;
		}
	}
	col = col/s; //divide by sample count
	}
	
	#ifdef DoF_Vignetting
		col *= vignette(IN.txcoord.xy,vignint);
	#endif
	
	return col;
}


float4 CCShadow (VS_OUTPUT_POST i, float2 vPos : VPOS) : COLOR
{
	float4 smpl = tex2D(InputSampler,i.txcoord);
	
	float factor = max(smpl.x, max(smpl.y, smpl.z));
	float factorM = (smpl.x + smpl.y + smpl.z)/3;
	float4 shadows = paramsS;
	float4 midtones = paramsM;
	float4 highlights = paramsH;
	
	float4 Color;
	
	if(factor < 0.1)	//Shadows
	{
		if(factor > 0.01)
		{
			factor = (factor + 0.09)*10;
			
			shadows.w = shadows.x; //.w is value backup
			shadows.x = ((1 - shadows.w) / 2) * factor;
			shadows.x += shadows.w;	//Adding backup
			
			shadows.w = shadows.y; //.w is value backup
			shadows.y = ((1 - shadows.w) / 2) * factor;
			shadows.y += shadows.w;	//Adding backup
			
			shadows.w = shadows.z; //.w is value backup
			shadows.z = ((1 - shadows.w) / 2) * factor;
			shadows.z += shadows.w;	//Adding backup
		}
		Color = float4(smpl.x * shadows.x, smpl.y * shadows.y, smpl.z * shadows.z, smpl.w);	
	}
	else if(factorM >= 0.1 && factorM <= 0.5)	//Middle-tones
	{
		if(factorM > 0.3)
		{
			factorM = (factorM - 0.31)*10;
			
			midtones.w = midtones.x; //.w is value backup
			midtones.x = ((1 - midtones.w) / 2) * factorM;
			midtones.x += midtones.w;	//Adding backup
			
			midtones.w = midtones.y; //.w is value backup
			midtones.y = ((1 - midtones.w) / 2) * factorM;
			midtones.y += midtones.w;	//Adding backup
			
			midtones.w = midtones.z; //.w is value backup
			midtones.z = ((1 - midtones.w) / 2) * factorM;
			midtones.z += midtones.w;	//Adding backup
		}
		else if(factorM <= 0.3)
		{
			factorM = (factorM - 0.1)*10;
			
			midtones.w = midtones.x;
			midtones.x = (1 - midtones.w) - (factorM * ((1 - midtones.w) / 2));
			midtones.x += midtones.w;
			
			midtones.w = midtones.y;
			midtones.y = (1 - midtones.w) - (factorM * ((1 - midtones.w) / 2));
			midtones.y += midtones.w;
			
			midtones.w = midtones.z;
			midtones.z = (1 - midtones.w) - (factorM * ((1 - midtones.w) / 2));
			midtones.z += midtones.w;
		}
		
		Color = float4(smpl.x * midtones.x, smpl.y * midtones.y, smpl.z * midtones.z, smpl.w);
	}		
	else if(factorM > 0.5)	//Hightlights
	{
		if(factorM <= 0.8)
		{
			factorM = (factorM - 0.51)*10;
			
			highlights.w = highlights.x;
			highlights.x = (1 - highlights.w) - (factorM * ((1 - highlights.w) / 2));
			highlights.x += highlights.w;
			
			highlights.w = highlights.y;
			highlights.y = (1 - highlights.w) - (factorM * ((1 - highlights.w) / 2));
			highlights.y += highlights.w;
			
			highlights.w = highlights.z;
			highlights.z = (1 - highlights.w) - (factorM * ((1 - highlights.w) / 2));
			highlights.z += highlights.w;
		}
	
		Color = float4(smpl.x * highlights.x, smpl.y * highlights.y, smpl.z * highlights.z, smpl.w);
	}
	else Color = smpl;
	
	float lum = Luminance(Color.xyz);
	
	Color = float4(lerp(float3(lum,lum,lum), Color.xyz, _Saturation),1);
	return 1-exp2(-_ExposureAdjustment * Color);
}


//--------------------------------------------------------------------------------------
// Bloom2
//--------------------------------------------------------------------------------------

float4 PS_ProcessBloom2 (VS_OUTPUT_POST IN, float2 vPos : VPOS) : COLOR 
{
	float4 col = tex2D(InputSampler, IN.txcoord);
	float4 color = tex2Dlod(InputSampler, float4(IN.txcoord,0,9));
	color = max(float4(0.0,0.0,0.0,0.0), color-threshhold2.x);
	float4 toBlend = saturate (color * BloomIntensity2);
	
	return 1-(1.00-col)*(1.68-toBlend);
}


//--------------------------------------------------------------------------------------
// Compiler 1
//--------------------------------------------------------------------------------------


technique PostProcess
{	
	pass P0
	{
#ifdef AA_MODE_0
		VertexShader = compile vs_3_0 VS_PostProcessSSAA();
		PixelShader  = compile ps_3_0 SSAA();
#endif
#ifdef AA_MODE_1
		VertexShader = compile vs_3_0 VS_PostProcessNFAA();
		PixelShader  = compile ps_3_0 NFAA();
#endif
#ifdef AA_MODE_2
		VertexShader = compile vs_3_0 VS_PostProcessFXAA();
		PixelShader  = compile ps_3_0 FXAA();
#endif
	}
}

technique PostProcess2
{	
	pass P0
	{
		VertexShader = compile vs_3_0 VS_PostProcess();
		PixelShader  = compile ps_3_0 PS_ProcessBloom();
	}
}

technique PostProcess3
{	
#ifdef DoF
	pass P0
	{
		VertexShader = compile vs_3_0 VS_PostProcess();
		PixelShader  = compile ps_3_0 PS_ProcessDoFBokeh();
	}
#endif
}

technique PostProcess4
{	
	pass P0
	{
		VertexShader = compile vs_3_0 VS_PostProcess();
		PixelShader  = compile ps_3_0 CCShadow();
	}
}

technique PostProcess5
{	
	pass P0
	{
		VertexShader = compile vs_3_0 VS_PostProcess();
		PixelShader  = compile ps_3_0 PS_ProcessBloom2();
	}
}